package com.smart.community.region.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smart.community.region.dto.PropertyHouseTypeQueryDTO;
import com.smart.community.region.entity.PropertyHouseType;
import com.smart.community.region.mapper.PropertyHouseTypeMapper;
import com.smart.community.region.service.IPropertyHouseTypeService;

import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;

/**
 * 物业公司户型表服务实现类
 * 
 * @author Wu.Liang
 * @version 1.0.0
 * @since 2025-01-30
 */
@Slf4j
@Service
public class PropertyHouseTypeServiceImpl extends ServiceImpl<PropertyHouseTypeMapper, PropertyHouseType> 
    implements IPropertyHouseTypeService {

    @Override
    @Cacheable(value = "property:house:type:company", key = "#propertyCompanyId", unless = "#result == null || #result.isEmpty()")
    public List<PropertyHouseType> getByPropertyCompanyId(Long propertyCompanyId) {
        long startTime = System.currentTimeMillis();
        log.info("根据物业公司ID查询户型列表，物业公司ID：{}", propertyCompanyId);
        
        try {
            LambdaQueryWrapper<PropertyHouseType> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(PropertyHouseType::getPropertyCompanyId, propertyCompanyId)
                       .eq(PropertyHouseType::getStatus, 1)
                       .orderByDesc(PropertyHouseType::getCreateTime);
            
            List<PropertyHouseType> result = this.list(queryWrapper);
            long endTime = System.currentTimeMillis();
            log.info("根据物业公司ID查询户型列表成功，耗时：{}ms", endTime - startTime);
            return result;
        } catch (Exception e) {
            long endTime = System.currentTimeMillis();
            log.error("根据物业公司ID查询户型列表失败，物业公司ID：{}，耗时：{}ms", propertyCompanyId, endTime - startTime, e);
            return new ArrayList<>();
        }
    }

    @Override
    @Cacheable(value = "property:house:type:companies", key = "#propertyCompanyIds.toString()", unless = "#result == null || #result.isEmpty()")
    public Map<Long, List<PropertyHouseType>> getByPropertyCompanyIds(List<Long> propertyCompanyIds) {
        long startTime = System.currentTimeMillis();
        log.info("根据物业公司ID列表查询户型列表，物业公司ID列表：{}", propertyCompanyIds);
        
        try {
            if (propertyCompanyIds == null || propertyCompanyIds.isEmpty()) {
                return new HashMap<>();
            }
            
            LambdaQueryWrapper<PropertyHouseType> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.in(PropertyHouseType::getPropertyCompanyId, propertyCompanyIds)
                       .eq(PropertyHouseType::getStatus, 1)
                       .orderByDesc(PropertyHouseType::getCreateTime);
            
            List<PropertyHouseType> houseTypes = this.list(queryWrapper);
            
            Map<Long, List<PropertyHouseType>> result = houseTypes.stream()
                    .collect(Collectors.groupingBy(PropertyHouseType::getPropertyCompanyId));
            long endTime = System.currentTimeMillis();
            log.info("根据物业公司ID列表查询户型列表成功，耗时：{}ms", endTime - startTime);
            return result;
        } catch (Exception e) {
            long endTime = System.currentTimeMillis();
            log.error("根据物业公司ID列表查询户型列表失败，耗时：{}ms", endTime - startTime, e);
            return new HashMap<>();
        }
    }

    @Override
    public IPage<PropertyHouseType> getPage(PropertyHouseTypeQueryDTO queryDTO) {
        long startTime = System.currentTimeMillis();
        log.info("分页查询户型列表，物业公司ID：{}，户型名称：{}，状态：{}", queryDTO.getPropertyCompanyId(), queryDTO.getHouseTypeName(), queryDTO.getStatus());
        
        try {
            // 创建分页对象
            Page<PropertyHouseType> page = new Page<>(queryDTO.getCurrent(), queryDTO.getSize());
            
            // 使用自定义的Mapper方法进行分页查询
            IPage<PropertyHouseType> result = baseMapper.selectPage(page, 
                                       queryDTO.getPropertyCompanyId(),
                                       queryDTO.getHouseTypeName(),
                                       queryDTO.getTotalAreaMin(),
                                       queryDTO.getTotalAreaMax(),
                                       queryDTO.getBedroomCount(),
                                       queryDTO.getOrientation(),
                                       queryDTO.getStatus());
            long endTime = System.currentTimeMillis();
            log.info("分页查询户型列表成功，耗时：{}ms", endTime - startTime);
            return result;
        } catch (Exception e) {
            long endTime = System.currentTimeMillis();
            log.error("分页查询户型列表失败，耗时：{}ms", endTime - startTime, e);
            return new Page<>();
        }
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    @CacheEvict(value = {
        "property:house:type:company",
        "property:house:type:companies", 
        "property:house:type:page",
        "property:house:type:check",
        "property:house:type:detail"
    }, allEntries = true)
    public boolean createHouseType(PropertyHouseType houseType) {
        log.info("创建户型，户型名称：{}，物业公司ID：{}", houseType.getHouseTypeName(), houseType.getPropertyCompanyId());
        
        // 检查户型名称是否已存在
        if (checkHouseTypeNameExists(houseType.getHouseTypeName(), houseType.getPropertyCompanyId(), null)) {
            throw new RuntimeException("户型名称已存在");
        }
        
        return this.save(houseType);
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    @CacheEvict(value = {
        "property:house:type:company",
        "property:house:type:companies", 
        "property:house:type:page",
        "property:house:type:check",
        "property:house:type:detail"
    }, allEntries = true)
    public boolean createHouseTypeForCompanies(PropertyHouseType houseType, List<Long> propertyCompanyIds) {
        log.info("批量创建户型，户型名称：{}，物业公司ID列表：{}", houseType.getHouseTypeName(), propertyCompanyIds);
        
        boolean success = true;
        for (Long propertyCompanyId : propertyCompanyIds) {
            PropertyHouseType newHouseType = new PropertyHouseType();
            // 复制属性
            newHouseType.setPropertyCompanyId(propertyCompanyId);
            newHouseType.setHouseTypeName(houseType.getHouseTypeName());
            newHouseType.setTotalArea(houseType.getTotalArea());
            newHouseType.setUsableArea(houseType.getUsableArea());
            newHouseType.setPublicArea(houseType.getPublicArea());
            newHouseType.setEfficiencyRate(houseType.getEfficiencyRate());
            newHouseType.setBedroomCount(houseType.getBedroomCount());
            newHouseType.setMasterBedroomCount(houseType.getMasterBedroomCount());
            newHouseType.setSecondaryBedroomCount(houseType.getSecondaryBedroomCount());
            newHouseType.setChildrenRoomCount(houseType.getChildrenRoomCount());
            newHouseType.setLivingRoomCount(houseType.getLivingRoomCount());
            newHouseType.setDiningRoomCount(houseType.getDiningRoomCount());
            newHouseType.setKitchenCount(houseType.getKitchenCount());
            newHouseType.setBathroomCount(houseType.getBathroomCount());
            newHouseType.setMasterBathroomCount(houseType.getMasterBathroomCount());
            newHouseType.setPublicBathroomCount(houseType.getPublicBathroomCount());
            newHouseType.setGuestBathroomCount(houseType.getGuestBathroomCount());
            newHouseType.setStudyRoomCount(houseType.getStudyRoomCount());
            newHouseType.setStorageRoomCount(houseType.getStorageRoomCount());
            newHouseType.setCloakroomCount(houseType.getCloakroomCount());
            newHouseType.setEntranceGardenCount(houseType.getEntranceGardenCount());
            newHouseType.setMasterBedroomArea(houseType.getMasterBedroomArea());
            newHouseType.setLivingRoomArea(houseType.getLivingRoomArea());
            newHouseType.setKitchenArea(houseType.getKitchenArea());
            newHouseType.setBathroomArea(houseType.getBathroomArea());
            newHouseType.setOrientation(houseType.getOrientation());
            newHouseType.setMasterBedroomOrientation(houseType.getMasterBedroomOrientation());
            newHouseType.setLivingRoomOrientation(houseType.getLivingRoomOrientation());
            newHouseType.setFloorPosition(houseType.getFloorPosition());
            newHouseType.setHasGarden(houseType.getHasGarden());
            newHouseType.setHasTerrace(houseType.getHasTerrace());
            newHouseType.setHasAttic(houseType.getHasAttic());
            newHouseType.setIsSquare(houseType.getIsSquare());
            newHouseType.setHasIrregularSpace(houseType.getHasIrregularSpace());
            newHouseType.setIsTransparent(houseType.getIsTransparent());
            newHouseType.setIsAllBright(houseType.getIsAllBright());
            newHouseType.setHasDynamicStaticSeparation(houseType.getHasDynamicStaticSeparation());
            newHouseType.setHasWetDrySeparation(houseType.getHasWetDrySeparation());
            newHouseType.setBalconyCount(houseType.getBalconyCount());
            newHouseType.setBalconyType(houseType.getBalconyType());
            newHouseType.setBalconyStyle(houseType.getBalconyStyle());
            newHouseType.setBayWindowCount(houseType.getBayWindowCount());
            newHouseType.setBayWindowType(houseType.getBayWindowType());
            newHouseType.setKitchenHasBalcony(houseType.getKitchenHasBalcony());
            newHouseType.setBathroomHasBathtub(houseType.getBathroomHasBathtub());
            newHouseType.setBathroomHasSeparation(houseType.getBathroomHasSeparation());
            newHouseType.setBathroomHasWindow(houseType.getBathroomHasWindow());
            newHouseType.setFloorHeight(houseType.getFloorHeight());
            newHouseType.setNetHeight(houseType.getNetHeight());
            newHouseType.setHasLoft(houseType.getHasLoft());
            newHouseType.setHasDuplex(houseType.getHasDuplex());
            newHouseType.setCanModify(houseType.getCanModify());
            newHouseType.setHasGiftArea(houseType.getHasGiftArea());
            newHouseType.setGiftAreaDesc(houseType.getGiftAreaDesc());
            newHouseType.setFloorPlanType(houseType.getFloorPlanType());
            newHouseType.setFloorPlanStatus(houseType.getFloorPlanStatus());
            newHouseType.setFloorPlanUrl(houseType.getFloorPlanUrl());
            newHouseType.setAdvantageTags(houseType.getAdvantageTags());
            newHouseType.setSuitableCrowd(houseType.getSuitableCrowd());
            newHouseType.setRemark(houseType.getRemark());
            newHouseType.setStatus(houseType.getStatus());
            
            // 检查户型名称是否已存在
            if (checkHouseTypeNameExists(newHouseType.getHouseTypeName(), propertyCompanyId, null)) {
                log.warn("户型名称已存在，跳过创建，户型名称：{}，物业公司ID：{}", newHouseType.getHouseTypeName(), propertyCompanyId);
                continue;
            }
            
            if (!this.save(newHouseType)) {
                success = false;
                log.warn("创建户型失败，户型名称：{}，物业公司ID：{}", newHouseType.getHouseTypeName(), propertyCompanyId);
            }
        }
        
        return success;
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    @CacheEvict(value = {
        "property:house:type:company",
        "property:house:type:companies", 
        "property:house:type:page",
        "property:house:type:check",
        "property:house:type:detail"
    }, allEntries = true)
    public boolean updateHouseType(PropertyHouseType houseType) {
        log.info("更新户型，户型ID：{}，户型名称：{}", houseType.getId(), houseType.getHouseTypeName());
        
        // 检查户型名称是否已存在
        if (checkHouseTypeNameExists(houseType.getHouseTypeName(), houseType.getPropertyCompanyId(), houseType.getId())) {
            throw new RuntimeException("户型名称已存在");
        }
        
        return this.updateById(houseType);
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    @CacheEvict(value = {
        "property:house:type:company",
        "property:house:type:companies", 
        "property:house:type:page",
        "property:house:type:check",
        "property:house:type:detail"
    }, allEntries = true)
    public boolean deleteHouseType(Long id) {
        log.info("删除户型，户型ID：{}", id);
        return this.removeById(id);
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    @CacheEvict(value = {
        "property:house:type:company",
        "property:house:type:companies", 
        "property:house:type:page",
        "property:house:type:check",
        "property:house:type:detail"
    }, allEntries = true)
    public boolean deleteBatchHouseTypes(List<Long> ids) {
        log.info("批量删除户型，户型ID列表：{}", ids);
        return this.removeByIds(ids);
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    @CacheEvict(value = {
        "property:house:type:company",
        "property:house:type:companies", 
        "property:house:type:page",
        "property:house:type:check",
        "property:house:type:detail"
    }, allEntries = true)
    public boolean updateStatus(Long id, Integer status) {
        log.info("更新户型状态，户型ID：{}，状态：{}", id, status);
        return baseMapper.updateStatus(id, status) > 0;
    }

    @Override
    @Cacheable(value = "property:house:type:check", key = "#houseTypeName + ':' + #propertyCompanyId + ':' + #excludeId", unless = "#result == false")
    public boolean checkHouseTypeNameExists(String houseTypeName, Long propertyCompanyId, Long excludeId) {
        log.info("检查户型名称是否已存在，户型名称：{}，物业公司ID：{}，排除ID：{}", houseTypeName, propertyCompanyId, excludeId);
        return baseMapper.checkHouseTypeNameExists(houseTypeName, propertyCompanyId, excludeId);
    }

    @Override
    @Cacheable(value = "property:house:type:detail", key = "#id", unless = "#result == null")
    public PropertyHouseType getHouseTypeById(Long id) {
        log.info("根据ID获取户型详情，户型ID：{}", id);
        return this.getById(id);
    }
}
